package com.brave.commonly.utils;

import android.app.Activity;
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.core.content.FileProvider;

import com.brave.commonly.CommonConfig;

import java.io.File;
import java.util.List;

/**
 * AppUtils
 * <br/>
 * {@link @author} brave tao
 * <br/>
 * {@link @time} 2019/7/23
 * <br/>
 * {@link @description} APP 工具类
 */
public final class AppUtils {
    private AppUtils() {
        throw new RuntimeException("cannot be instantiated");
    }

    private static Context getContext() {
        return CommonConfig.getContext();
    }

    /**
     * 获取 PackageInfo 对象
     */
    public static PackageInfo getPackageInfo() {
        try {
            PackageManager packageManager = getContext().getPackageManager();
            return packageManager.getPackageInfo(
                    getContext().getPackageName(), 0);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取App包名
     */
    public static String getAppPackageName() {
        return CommonConfig.getApplication().getPackageName();
    }

    /**
     * 获取App路径
     */
    public static String getAppPath() {
        return getAppPath(getAppPackageName());
    }

    /**
     * 获取App路径
     *
     * @param packageName 包名
     */
    public static String getAppPath(final String packageName) {
        if (isSpace(packageName)) {
            return "";
        }
        PackageInfo pi = getPackageInfo();
        return pi == null ? null : pi.applicationInfo.sourceDir;
    }

    /**
     * 获取App图标
     */
    public static Drawable getAppIcon() {
        return getAppIcon(getAppPackageName());
    }

    /**
     * 获取App图标
     *
     * @param packageName 包名
     */
    public static Drawable getAppIcon(final String packageName) {
        if (isSpace(packageName)) {
            return null;
        }
        try {
            PackageManager pm = CommonConfig.getApplication().getPackageManager();
            PackageInfo pi = pm.getPackageInfo(packageName, 0);
            return pi == null ? null : pi.applicationInfo.loadIcon(pm);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获取 APP 名称
     */
    public static String getAppName() {
        PackageInfo packageInfo = getPackageInfo();
        return null == packageInfo ? null : getContext().getResources().getString(
                packageInfo.applicationInfo.labelRes);
    }

    /**
     * 获取 APP 版本名
     */
    public static String getVersionName() {
        PackageInfo packageInfo = getPackageInfo();
        return null == packageInfo ? null : packageInfo.versionName;
    }

    /**
     * 获取 APP 版本号
     */
    public static int getVersionCode() {
        PackageInfo packageInfo = getPackageInfo();
        return null == packageInfo ? -1 : packageInfo.versionCode;
    }

    /**
     * 安装App
     *
     * @param filePath 文件路径
     */
    public static void installApp(final String filePath) {
        installApp(getFileByPath(filePath));
    }

    /**
     * 安装App
     *
     * @param file 文件
     */
    public static void installApp(final File file) {
        if (!isFileExists(file)) {
            return;
        }
        getContext().startActivity(getInstallAppIntent(file, true));
    }

    /**
     * 安装App
     *
     * @param activity    活动
     * @param filePath    文件路径
     * @param requestCode 请求码
     */
    public static void installApp(final Activity activity,
                                  final String filePath,
                                  final int requestCode) {
        installApp(activity, getFileByPath(filePath), requestCode);
    }

    /**
     * 安装App
     *
     * @param activity    活动
     * @param file        文件
     * @param requestCode 请求码
     */
    public static void installApp(final Activity activity,
                                  final File file,
                                  final int requestCode) {
        if (!isFileExists(file)) return;
        activity.startActivityForResult(getInstallAppIntent(file), requestCode);
    }

    /**
     * 卸载APP
     *
     * @param packageName 包名
     */
    public static void uninstallApp(final String packageName) {
        if (isSpace(packageName)) return;
        CommonConfig.getContext().startActivity(getUninstallAppIntent(packageName, true));
    }

    /**
     * 卸载APP
     *
     * @param activity    活动
     * @param packageName 包名
     * @param requestCode 请求码
     */
    public static void uninstallApp(final Activity activity,
                                    final String packageName,
                                    final int requestCode) {
        if (isSpace(packageName)) return;
        activity.startActivityForResult(getUninstallAppIntent(packageName), requestCode);
    }

    /**
     * 判断 App 是否安装
     *
     * @param pkgName 包名
     */
    public static boolean isAppInstalled(@NonNull final String pkgName) {
        PackageManager packageManager = CommonConfig.getApplication().getPackageManager();
        try {
            return packageManager.getApplicationInfo(pkgName, 0) != null;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 是否具ROOT权限
     */
    public static boolean isAppRoot() {
        ShellUtils.CommandResult result = ShellUtils.execCmd("echo root", true);
        if (result.result == 0) {
            return true;
        }
        if (result.errorMsg != null) {
            Log.d("AppUtils", "isAppRoot() called" + result.errorMsg);
        }
        return false;
    }

    /**
     * 是否为Debug版本
     */
    public static boolean isAppDebug() {
        return isAppDebug(getAppPackageName());
    }

    /**
     * 是否为Debug版本
     *
     * @param packageName 包名
     */
    public static boolean isAppDebug(final String packageName) {
        if (isSpace(packageName)) {
            return false;
        }
        try {
            PackageManager pm = CommonConfig.getApplication().getPackageManager();
            ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
            return ai != null && (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 是否为APP
     */
    public static boolean isAppSystem() {
        return isAppSystem(getAppPackageName());
    }

    /**
     * 是否为APP
     *
     * @param packageName 包名
     */
    public static boolean isAppSystem(final String packageName) {
        if (isSpace(packageName)) {
            return false;
        }
        try {
            PackageManager pm = CommonConfig.getApplication().getPackageManager();
            ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
            return ai != null && (ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * App是否正在运行
     *
     * @param pkgName 包名
     */
    public static boolean isAppRunning(@NonNull final String pkgName) {
        int uid;
        PackageManager packageManager = CommonConfig.getApplication().getPackageManager();
        try {
            ApplicationInfo ai = packageManager.getApplicationInfo(pkgName, 0);
            if (ai == null) {
                return false;
            }
            uid = ai.uid;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return false;
        }
        ActivityManager am = (ActivityManager) CommonConfig.getApplication().getSystemService(Context.ACTIVITY_SERVICE);
        if (am != null) {
            List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(Integer.MAX_VALUE);
            if (taskInfo != null && taskInfo.size() > 0) {
                for (ActivityManager.RunningTaskInfo aInfo : taskInfo) {
                    if (pkgName.equals(aInfo.baseActivity.getPackageName())) {
                        return true;
                    }
                }
            }
            List<ActivityManager.RunningServiceInfo> serviceInfo = am.getRunningServices(Integer.MAX_VALUE);
            if (serviceInfo != null && serviceInfo.size() > 0) {
                for (ActivityManager.RunningServiceInfo aInfo : serviceInfo) {
                    if (uid == aInfo.uid) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    /**
     * 打开App
     *
     * @param packageName 包名
     */
    public static void launchApp(final String packageName) {
        if (isSpace(packageName)) {
            return;
        }
        getContext().startActivity(getLaunchAppIntent(packageName, true));
    }

    /**
     * 打开App
     *
     * @param activity    活动
     * @param packageName 包名
     * @param requestCode 请求码
     */
    public static void launchApp(final Activity activity,
                                 final String packageName,
                                 final int requestCode) {
        if (isSpace(packageName)) {
            return;
        }
        activity.startActivityForResult(getLaunchAppIntent(packageName), requestCode);
    }

    /**
     * 重启App
     */
    public static void relaunchApp() {
        relaunchApp(false);
    }

    /**
     * 重启App
     *
     * @param isKillProcess 杀死进程
     */
    public static void relaunchApp(final boolean isKillProcess) {
        PackageManager packageManager = CommonConfig.getApplication().getPackageManager();
        Intent intent = packageManager.getLaunchIntentForPackage(getAppPackageName());
        if (intent == null) {
            return;
        }
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK
        );
        getContext().startActivity(intent);
        if (!isKillProcess) {
            return;
        }
        android.os.Process.killProcess(android.os.Process.myPid());
        System.exit(0);
    }

    /**
     * 退出APP
     */
    public static void exitApp() {
        ActivityUtils.getInstance().clearActivity();
        System.exit(0);
    }

    /**
     * 打开指定APP的详情界面
     *
     * @param packageName 包名
     */
    public static void openAppDetails(String packageName) {
        SettingsUtils.openAppDetails(packageName);
    }

    /**
     * 打开APP的详情界面
     */
    public static void openAppDetails() {
        SettingsUtils.openAppDetails();
    }

    ///////////////////////////////////////////////////////////////////////////
    // 其他的帮助
    ///////////////////////////////////////////////////////////////////////////

    /**
     * 是否存在文件
     *
     * @param file 文件
     */
    private static boolean isFileExists(final File file) {
        return file != null && file.exists();
    }

    /**
     * 获取文件
     *
     * @param filePath 文件路径
     */
    private static File getFileByPath(final String filePath) {
        return isSpace(filePath) ? null : new File(filePath);
    }

    /**
     * 是否存在空格
     *
     * @param s 字符串
     */
    private static boolean isSpace(final String s) {
        if (s == null) {
            return true;
        }
        for (int i = 0, len = s.length(); i < len; ++i) {
            if (!Character.isWhitespace(s.charAt(i))) {
                return false;
            }
        }
        return true;
    }

    /**
     * 获取安装意图
     *
     * @param file 文件
     */
    private static Intent getInstallAppIntent(final File file) {
        return getInstallAppIntent(file, false);
    }

    /**
     * 获取安装意图
     *
     * @param file      文件
     * @param isNewTask 是否需要后台启动
     */
    private static Intent getInstallAppIntent(final File file, final boolean isNewTask) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        Uri data;
        String type = "application/vnd.android.package-archive";
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
            data = Uri.fromFile(file);
        } else {
            String authority = getAppPackageName() + ".utils.provider";
            data = FileProvider.getUriForFile(getContext(), authority, file);
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        }
        CommonConfig.getApplication().grantUriPermission(getAppPackageName(),
                data, Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setDataAndType(data, type);
        return isNewTask ? intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) : intent;
    }

    /**
     * 获取卸载意图
     *
     * @param packageName 包名
     */
    private static Intent getUninstallAppIntent(final String packageName) {
        return getUninstallAppIntent(packageName, false);
    }

    /**
     * 获取卸载意图
     *
     * @param packageName 包名
     * @param isNewTask   是否需要后台启动
     */
    private static Intent getUninstallAppIntent(final String packageName, final boolean isNewTask) {
        Intent intent = new Intent(Intent.ACTION_DELETE);
        intent.setData(Uri.parse("package:" + packageName));
        return isNewTask ? intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) : intent;
    }

    /**
     * 获取启动APP意图
     *
     * @param packageName 包名
     */
    private static Intent getLaunchAppIntent(final String packageName) {
        return getLaunchAppIntent(packageName, false);
    }

    /**
     * 获取启动APP意图
     *
     * @param packageName 包名
     * @param isNewTask   是否在后台启动
     */
    private static Intent getLaunchAppIntent(final String packageName, final boolean isNewTask) {
        Intent intent = CommonConfig.getApplication().getPackageManager().getLaunchIntentForPackage(packageName);
        if (intent == null) {
            return null;
        }
        return isNewTask ? intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) : intent;
    }
}